home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Environments / Clean 1.2.4 / IOInterface / dialogLayout.icl < prev    next >
Encoding:
Modula Implementation  |  1997-04-23  |  22.7 KB  |  616 lines  |  [TEXT/3PRM]

  1. implementation module dialogLayout;
  2.  
  3. //    Dialog layout calculations
  4.  
  5. import StdClass,StdReal,StdInt,StdMisc,StdString,StdBool;
  6. import    commonDef, mac_types, quickdraw, pointer;
  7. import    deltaFont;
  8. from    deltaPicture import DrawFunction, Picture;
  9.  
  10. ::    ItemInfo
  11.     :==    (    [(DialogItemId,String)],
  12.             [(DialogItemId,DialogItemId)],
  13.             [(DialogItemId,[(DialogItemId,Bool)])],
  14.             [(DialogItemId,ControlState)]    );
  15. ::    DialogInfo
  16.     :==    ItemInfo;
  17.  
  18. ::    DialogDef *s *io
  19.     =  PropertyDialog DialogId DialogTitle [DialogAttribute] (SetFunction s io)
  20.                       (ResetFunction s io) [DialogItem s io]
  21.     |  CommandDialog  DialogId DialogTitle [DialogAttribute]
  22.                       DialogItemId [DialogItem s io]
  23.     |  AboutDialog    ApplicationName PictureDomain [DrawFunction] (AboutHelpDef s io);
  24.  
  25. ::    DialogId        :== Int;
  26. ::    DialogTitle        :== String;
  27. ::    DialogAttribute
  28.     =    DialogPos    Measure Measure
  29.     |    DialogSize   Measure Measure
  30.     |    DialogMargin Measure Measure
  31.     |    ItemSpace    Measure Measure
  32.     |    StandByDialog;
  33. ::    Measure            =    MM Real | Inch Real | Pixel Int;
  34.  
  35. ::    ApplicationName    :== String;
  36. ::    AboutHelpDef *s *io
  37.     =    AboutHelp ItemTitle (AboutHelpFunction s io)
  38.     |    NoHelp;
  39. ::    AboutHelpFunction *s *io    :== s -> *(io -> (s,io));
  40.  
  41. ::    DialogItem *s *io
  42.     =    DialogButton     DialogItemId ItemPos ItemTitle SelectState
  43.                                         (ButtonFunction s io)
  44.     |    DialogIconButton DialogItemId ItemPos PictureDomain IconLook SelectState
  45.                                         (ButtonFunction s io)
  46.     |    StaticText         DialogItemId ItemPos String
  47.     |    DynamicText         DialogItemId ItemPos TextWidth String
  48.     |    EditText         DialogItemId ItemPos TextWidth NrEditLines String
  49.     |    DialogPopUp         DialogItemId ItemPos SelectState DialogItemId
  50.                                         [RadioItemDef s io]
  51.     |    RadioButtons     DialogItemId ItemPos RowsOrColumns DialogItemId
  52.                                         [RadioItemDef s io]
  53.     |    CheckBoxes         DialogItemId ItemPos RowsOrColumns
  54.                                         [CheckBoxDef s io]
  55.     |    Control             DialogItemId ItemPos PictureDomain SelectState
  56.                                         ControlState ControlLook ControlFeel
  57.                                         (DialogFunction s io);
  58.  
  59. ::    DialogItemId    :==    Int;
  60. ::    ItemPos            =    Left | Center | Right | RightTo DialogItemId
  61.                     |    Below DialogItemId | XOffset DialogItemId Measure
  62.                     |    YOffset DialogItemId Measure | XY Measure Measure
  63.                     |    ItemBox Int Int Int Int;
  64. ::    IconLook        :== SelectState -> [DrawFunction];
  65. ::    TextWidth        :== Measure;
  66. ::    NrEditLines        :== Int;
  67. ::    RowsOrColumns    =    Rows Int | Columns Int;
  68.  
  69. ::    RadioItemDef *s *io
  70.     =    RadioItem DialogItemId ItemTitle SelectState            (DialogFunction s io);
  71. ::    CheckBoxDef     *s *io
  72.     =    CheckBox  DialogItemId ItemTitle SelectState MarkState    (DialogFunction s io);
  73.  
  74. ::    ControlState    =    BoolCS Bool | IntCS Int | RealCS Real | StringCS String
  75.                     |    PairCS ControlState ControlState | ListCS [ControlState];
  76. ::    ControlLook        :== SelectState -> ControlState -> [DrawFunction];
  77. ::    ControlFeel        :== MouseState  -> ControlState -> (ControlState,[DrawFunction]);
  78.  
  79. ::    SetFunction    *s *io :== ButtonFunction s io;
  80. ::    ResetFunction  *s *io :== ButtonFunction s io;
  81. ::    DialogFunction *s *io
  82.     :== DialogInfo -> (DialogState s io) -> DialogState s io;
  83. ::    ButtonFunction *s *io
  84.     :== DialogInfo -> (s -> *(io -> (s,io)));
  85.  
  86. ::    NoticeDef        =    Notice [String] NoticeButtonDef [NoticeButtonDef];
  87. ::    NoticeButtonDef    =    NoticeButton NoticeButtonId ItemTitle;
  88. ::    NoticeButtonId    :==    Int;
  89.  
  90. ::    *DialogState *s *io
  91.     :==    (    !DialogRep s io,
  92.             !Toolbox    );
  93. ::    DialogRep     *s *io
  94.     :==    (    !DialogHandle s io,
  95.             !DialogPtr    );
  96. ::    NoticeHandle *s *io
  97.     =    NoticeH Rect [DialogItem s io];
  98. ::    DialogHandle *s *io
  99.     =    DialogH DialogId DialogTitle DialogMode Rect [PopUpHandle]
  100.                 [DialogItem s io] DialogDefInfo;
  101. ::    DialogMode
  102.     =    Modal
  103.     |    Modeless;
  104. ::    DialogDefInfo
  105.     =    DialogRest DialogKind [DialogAttribute] DialogItemId;
  106.     //    The last argument is the id of the default button.
  107. ::    DialogKind
  108.     =    Property
  109.     |    Command;
  110. ::    PopUpHandle
  111.     :==    (    !DialogItemId,
  112.             !MacMenuHandle    );
  113.  
  114. ::    ItPos
  115.     :== (    !DialogItemId,
  116.             !ItemPos,
  117.             !Rect,
  118.             ![CPos]    );
  119. ::    CPos
  120.     :==    (    !DialogItemId,
  121.             !Rect    );
  122.  
  123.  
  124. DialogLayoutError :: String String -> .x;
  125. DialogLayoutError f error = Error f "dialogLayout" error;
  126.  
  127.  
  128. CreateDialogState :: !(!DialogRep s io, !Toolbox) -> DialogState s io;
  129. CreateDialogState dState = dState;
  130.  
  131. UnpackDialogState :: !(DialogState s io) -> (!DialogRep s io, !Toolbox);
  132. UnpackDialogState dState = dState;
  133.  
  134. DialogInfoToItemInfo :: !DialogInfo -> ItemInfo;
  135. DialogInfoToItemInfo dInfo = dInfo;
  136.  
  137. DialogHandleToDialogInfo :: !(DialogHandle s io) -> DialogInfo;
  138. DialogHandleToDialogInfo (DialogH _ _ _ _ _ items _) = CreateDialogInfo items;
  139.  
  140. CreateDialogInfo :: ![DialogItem s io] -> DialogInfo;
  141. CreateDialogInfo [EditText id ps tw nl text : rest]
  142.     =    ([(id,text):edits],radios,checks,ctrls);
  143.     where {
  144.         (edits,radios,checks,ctrls) = CreateDialogInfo rest;
  145.     };
  146. CreateDialogInfo [DialogPopUp id ps ab di rs : rest]
  147.     =    (edits,[(id,di):radios],checks,ctrls);
  148.     where {
  149.         (edits,radios,checks,ctrls) = CreateDialogInfo rest;
  150.     };
  151. CreateDialogInfo [RadioButtons id ps rc di rs : rest]
  152.     =    (edits,[(id,di):radios],checks,ctrls);
  153.     where {
  154.         (edits,radios,checks,ctrls) = CreateDialogInfo rest;
  155.     };
  156. CreateDialogInfo [CheckBoxes id ps rc boxes : rest]
  157.     =    (edits,radios,[(id,CreateCheckBoxesInfo boxes):checks],ctrls);
  158.     where {
  159.         (edits,radios,checks,ctrls) = CreateDialogInfo rest;
  160.     };
  161. CreateDialogInfo [Control id ps pd ab state cl cf df : rest]
  162.     =    (edits,radios,checks,[(id,state):ctrls]);
  163.     where {
  164.         (edits,radios,checks,ctrls) = CreateDialogInfo rest;
  165.     };
  166. CreateDialogInfo [_ : rest]    = CreateDialogInfo rest;
  167. CreateDialogInfo _            = ([],[],[],[]);
  168.  
  169. CreateCheckBoxesInfo :: [CheckBoxDef s io] -> [(DialogItemId,Bool)];
  170. CreateCheckBoxesInfo [CheckBox id _ _ mark _ : rest]
  171.     =    [(id,MarkToBool mark) : CreateCheckBoxesInfo rest];
  172. CreateCheckBoxesInfo _ = [];
  173.  
  174. MarkToBool :: MarkState -> Bool;
  175. MarkToBool Mark    = True;
  176. MarkToBool _    = False;
  177.  
  178.  
  179. MMPerInch    :== 25.4;
  180. LineHeight    :== 16;        // The line height of the Macintosh dialog font: Plain Chicago 12.
  181. BaseOfs        :== 12;        // Ascent+Leading of the Macintosh dialog font.
  182. MinButWid    :== 55;
  183. ButHgt        :== 20;
  184. RadBoxWid    :== 32;
  185. PopUpWid    :== 24;
  186. DummyItPos    :== (0,Left,(0,0,0,0),[]);
  187.  
  188.  
  189. /*    Calculate the precise position (in pixels) of each dialog item. */
  190.  
  191. CalcItemBoxes :: !(!Int,!Int) !(!Int,!Int) ![DialogItem s io] -> (!Int,!Int,![DialogItem s io]);
  192. CalcItemBoxes margins=:(hmg,vmg) spaces=:(hsp,vsp) items
  193.     =    (width, hgt + vmg, AddItemBoxes pos3 items);
  194.     where {
  195.         pos1            = CalcItemSizes DialogFont items;
  196.         width            = wid + hmg;
  197.         (wid,hgt,pos2)    = CalcItemPositions hmg (vmg - vsp) margins spaces pos1 [];
  198.         pos3            = RenterItems width hmg pos2 [];
  199.     };
  200.  
  201. /*    Calculate the width and height of each item. */
  202.  
  203. CalcItemSizes :: !Font ![DialogItem s io] -> [ItPos];
  204. CalcItemSizes dfont [DialogButton id pos txt _ _ : items]
  205.     =    [(id,pos,CalcButtonSize dfont pos txt,[]) : CalcItemSizes dfont items];
  206. CalcItemSizes dfont [DialogIconButton id pos pd _ _ _ : items]
  207.     =    [(id,pos,CalcUserDefSize pos pd,[]) : CalcItemSizes dfont items];
  208. CalcItemSizes dfont [StaticText id pos txt : items]
  209.     =    [(id,pos,CalcStaticTextSize dfont pos txt,[]) : CalcItemSizes dfont items];
  210. CalcItemSizes dfont [DynamicText id pos wid _ : items]
  211.     =    [(id,pos,CalcEditTextSize pos wid 1,[]) : CalcItemSizes dfont items];
  212. CalcItemSizes dfont [EditText id pos wid nrl _ : items]
  213.     =    [(id,pos,CalcEditTextSize pos wid nrl,[]) : CalcItemSizes dfont items];
  214. CalcItemSizes dfont [DialogPopUp id pos _ _ buts : items]
  215.     =    [(id,pos,CalcPopUpSize dfont pos buts,[]) : CalcItemSizes dfont items];
  216. CalcItemSizes dfont [RadioButtons id pos roc _ buts : items]
  217.     =    [(id,pos,CalcRadioBoxSize pos roc nr maxw,[]) : CalcItemSizes dfont items];
  218.     where {
  219.         (nr,maxw) = RadioButtonsNr_and_MaxWidth dfont 0 0 buts;
  220.     };
  221. CalcItemSizes dfont [CheckBoxes id pos roc boxes : items]
  222.     =    [(id,pos,CalcRadioBoxSize pos roc nr maxw,[]) : CalcItemSizes dfont items];
  223.     where {
  224.         (nr,maxw) = CheckBoxesNr_and_MaxWidth dfont 0 0 boxes;
  225.     };
  226. CalcItemSizes dfont [Control id pos pd _ _ _ _ _ : items]
  227.     =    [(id,pos,CalcUserDefSize pos pd,[]) : CalcItemSizes dfont items];
  228. CalcItemSizes _ [] = [];
  229. CalcItemSizes _ _
  230.     =    DialogLayoutError "CalcItemSizes" "Unknown dialog item";
  231.  
  232. CalcButtonSize :: !Font !ItemPos !String -> Rect;
  233. CalcButtonSize dfont (ItemBox l t w h) _ = ProperRect (l,t,w,h);
  234. CalcButtonSize dfont _ title = (0,0,bwid,ButHgt);
  235.     where {
  236.         bwid = Max MinButWid (12 + FontStringWidth title dfont);
  237.     };
  238.  
  239. CalcUserDefSize    :: !ItemPos !PictureDomain -> Rect;
  240. CalcUserDefSize (ItemBox l t w h) _    = ProperRect (l,t,w,h);
  241. CalcUserDefSize pos ((l,t),(r,b))    = (0,0,ABS (r - l),ABS (b - t));
  242.  
  243. CalcStaticTextSize :: !Font !ItemPos !String -> Rect;
  244. CalcStaticTextSize _ (ItemBox l t w h) _ = ProperRect (l,t,w,h);
  245. CalcStaticTextSize dfont pos text = (0,0,4 + FontStringWidth text dfont,LineHeight);
  246.  
  247. CalcEditTextSize :: !ItemPos !Measure !Int -> Rect;
  248. CalcEditTextSize (ItemBox l t w h) _ _ = ProperRect (l,t,w,h);
  249. CalcEditTextSize _ wid nrl = (0,0,HorMeasureToPixels wid,nrl * LineHeight);
  250.  
  251. CalcPopUpSize :: !Font !ItemPos ![RadioItemDef s io] -> Rect;
  252. CalcPopUpSize _ (ItemBox l t w h) _ = ProperRect (l,t,w,h);
  253. CalcPopUpSize dfont _ buts = (0,0,PopUpWid + bwid,LineHeight);
  254.     where {
  255.         (nr,bwid) = RadioButtonsNr_and_MaxWidth dfont 0 0 buts;
  256.     };
  257.  
  258. CalcRadioBoxSize :: !ItemPos !RowsOrColumns !Int !Int -> Rect;
  259. CalcRadioBoxSize (ItemBox l t w h) (Rows nr) nb _
  260.     =  ProperRect (l,t,w * UpDiv nb nr, h * nr);
  261. CalcRadioBoxSize (ItemBox l t w h) (Columns nc) nb _
  262.     =  ProperRect (l,t,w * nc,h * UpDiv nb nc);
  263. CalcRadioBoxSize pos (Rows nr) nb wid
  264.     =  (0,0,(wid + RadBoxWid) * UpDiv nb nr, LineHeight * nr);
  265. CalcRadioBoxSize pos (Columns nc) nb wid
  266.     =  (0,0,(wid + RadBoxWid) * nc,LineHeight * UpDiv nb nc);
  267.  
  268. RadioButtonsNr_and_MaxWidth    :: !Font !Int !Int ![RadioItemDef s io] -> (!Int,!Int);
  269. RadioButtonsNr_and_MaxWidth dfont nr maxw [RadioItem _ text _ _ : rest]
  270.     =    RadioButtonsNr_and_MaxWidth dfont (inc nr) maxw` rest;
  271.     where {
  272.         maxw` = Max maxw (FontStringWidth text dfont);
  273.     };
  274. RadioButtonsNr_and_MaxWidth _ nr maxw _ = (nr,maxw);
  275.  
  276. CheckBoxesNr_and_MaxWidth :: !Font !Int !Int ![CheckBoxDef s io] -> (!Int,!Int);
  277. CheckBoxesNr_and_MaxWidth dfont nr maxw [CheckBox _ text _ _ _ : rest]
  278.     =    CheckBoxesNr_and_MaxWidth dfont (inc nr) maxw` rest;
  279.     where {
  280.         maxw` = Max maxw (FontStringWidth text dfont);
  281.     };
  282. CheckBoxesNr_and_MaxWidth _ nr maxw _ = (nr,maxw);
  283.  
  284. ProperRect :: !Rect -> Rect;
  285. ProperRect (l,t,w,h) = (ABS l, ABS t, ABS w, ABS h);
  286.  
  287. UpDiv :: !Int !Int -> Int;
  288. UpDiv a b
  289. |    b        == 0    = a;
  290. |    a mod b    == 0    = a/b;
  291.                     = inc (a/b);
  292.  
  293. Div :: !Int !Int -> Int;
  294. Div a b
  295. |    b == 0    = a;
  296.             = a/b;
  297.  
  298. /*    After calculating width and height of each item the positions can be determined.
  299.     On the fly the width and height of the dialog are calculated.
  300.     (NB: Renter = Right or Center)
  301. */
  302. CalcItemPositions :: !Int !Int !(!Int,!Int) !(!Int,!Int) ![ItPos] ![ItPos] -> (!Int,!Int,![ItPos]);
  303. CalcItemPositions maxx maxy mg=:(hm,vm) sp=:(hs,vs) [(id,Left,(l,t,w,h),ci):rest] poss
  304.     =    CalcItemPositions maxx` (t` + h) mg sp rest [(id,Left,(hm,t`,w,h),ci):poss];
  305.     where {
  306.         maxx` = Max maxx (hm + w);
  307.         t`=: maxy + vs;
  308.     };
  309. CalcItemPositions maxx maxy mg=:(hm,vm) sp=:(hs,vs) [(id,Center,(l,t,w,h),ci):rest] poss
  310.     =    CalcItemPositions maxx` (t` + h) mg sp rest [(id,Center,(hm,t`,w,h),ci):poss];
  311.     where {
  312.         maxx` = Max maxx (hm + w);
  313.         t`=: maxy + vs;
  314.     };
  315. CalcItemPositions maxx maxy mg=:(hm,vm) sp=:(hs,vs) [(id,Right,(l,t,w,h),ci):rest] poss
  316.     =    CalcItemPositions maxx` (t` + h) mg sp rest [(id,Right,(hm,t`,w,h),ci):poss];
  317.     where {
  318.         maxx` = Max maxx (hm + w);  t`=: maxy + vs;
  319.     };
  320. CalcItemPositions maxx maxy mg=:(hm,vm) sp=:(hs,vs) [item1=:(id,RightTo ri,rc,ci):rest] poss
  321. |    exists    = CalcItemPositions maxx1 maxy1 mg sp rest (Concat items poss`);
  322.             = CalcItemPositions maxx2 (t` + h) mg sp rest [(id,Left,(hm,t`,w,h),ci):poss];
  323.     where {
  324.         (maxx1,maxy1,items) = PositionRightTo maxx maxy hs ri item1 item2;
  325.         (exists,item2,poss`)= RemoveItPos ri poss;
  326.         maxx2 = Max maxx (hm + w);  t` = maxy + vs;  (l,t,w,h) = rc;
  327.     };
  328. CalcItemPositions maxx maxy mg=:(hm,vm) sp=:(hs,vs) [item1=:(id,XOffset ri ofs,rc,ci):rest] poss
  329. |    exists    = CalcItemPositions maxx1 maxy1 mg sp rest (Concat items poss`);
  330.             = CalcItemPositions maxx2 (t` + h) mg sp rest [(id,Left,(hm,t`,w,h),ci):poss];
  331.     where {
  332.         (maxx1,maxy1,items) = PositionRightTo maxx maxy (HorMeasureToPixels ofs) ri item1 item2;
  333.         (exists,item2,poss`)= RemoveItPos ri poss;
  334.         maxx2 = Max maxx (hm + w);  t` = maxy + vs;  (l,t,w,h) = rc;
  335.     };
  336. CalcItemPositions maxx maxy mg=:(hm,vm) sp=:(hs,vs) [item1=:(id,Below ri,rc,ci):rest] poss
  337. |    exists    = CalcItemPositions maxx1 maxy1 mg sp rest [bpos,item2:poss`];
  338.             = CalcItemPositions maxx2 (t` + h) mg sp rest [(id,Left,(hm,t`,w,h),ci):poss];
  339.     where {
  340.         (maxx1,maxy1,bpos)  = PositionBelow maxx maxy vs hm item1 item2;
  341.         (exists,item2,poss`)= RemoveItPos ri poss;
  342.         maxx2 = Max maxx (hm + w);  t` = maxy + vs;  (l,t,w,h) = rc;
  343.     };
  344. CalcItemPositions maxx maxy mg=:(hm,vm) sp=:(hs,vs) [item1=:(id,YOffset ri ofs,rc,ci):rest] poss
  345. |    exists    = CalcItemPositions maxx1 maxy1 mg sp rest [bpos,item2:poss`];
  346.             = CalcItemPositions maxx2 (t` + h) mg sp rest [(id,Left,(hm,t`,w,h),ci):poss];
  347.     where {
  348.         (maxx1,maxy1,bpos)  = PositionBelow maxx maxy (VerMeasureToPixels ofs) hm item1 item2;
  349.         (exists,item2,poss`)= RemoveItPos ri poss;
  350.         maxx2 = Max maxx (hm + w);  t` = maxy + vs;  (l,t,w,h) = rc;
  351.     };
  352. CalcItemPositions maxx maxy mg sp [(id,ps=:XY x y,(l,t,w,h),ci):rest] poss
  353.     =    CalcItemPositions maxx` maxy` mg sp rest [(id,ps,(l`,t`,w,h),ci):poss];
  354.     where {
  355.         maxx`    = Max maxx (l` + w);        maxy`    = Max maxx (t` + h);
  356.         l`        = HorMeasureToPixels x;        t`        = VerMeasureToPixels y;
  357.     };
  358. CalcItemPositions maxx maxy mg sp [pos=:(id,ps=:ItemBox l t w h,rc,ci):rest] poss
  359.     =    CalcItemPositions (Max maxx (l + w)) (Max maxy (t + h)) mg sp rest [pos:poss];
  360. CalcItemPositions maxx maxy mg sp [] poss = (maxx,maxy,poss);
  361.  
  362. PositionRightTo    :: !Int !Int !Int !Int !ItPos !ItPos -> (!Int,!Int,![ItPos]);
  363. PositionRightTo maxx maxy ofs id item1=:(i1,p1,r1,c1) (i2,Center,r2,poss)
  364. |    id == i2    = (mx1,my1,[(i2,Center,r2,[(i1,(l1,t2,w1,h1)):poss])]);
  365.                 = (mx2,my2,[(i2,Center,r2,poss`)]);
  366.     where {
  367.         mx1    = Max maxx (l1 + w1);    my1                = Max maxy (t2 + h1);
  368.         l1    = l2+w2+ofs;            (ld,td,w1,h1)    = r1;        (l2,t2,w2,h2) = r2;
  369.         (mx2,my2,poss`) = RightToRenter maxx maxy ofs id item1 poss;
  370.     };
  371. PositionRightTo maxx maxy ofs id item1=:(i1,p1,r1,c1) (i2,Right,r2,poss)
  372. |    id == i2    = (mx1,my1,[(i2,Right,r2,[(i1,(l1,t2,w1,h1)):poss])]);
  373.                 = (mx2,my2,[(i2,Right,r2,poss`)]);
  374.     where {
  375.         mx1    = Max maxx (l1 + w1);    my1                = Max maxy (t2 + h1);
  376.         l1    = l2+w2+ofs;             (ld,td,w1,h1)    = r1;        (l2,t2,w2,h2) = r2;
  377.         (mx2,my2,poss`) = RightToRenter maxx maxy ofs id item1 poss;
  378.     };
  379. PositionRightTo maxx maxy ofs id (i1,p1,(ld,td,w1,h1),c1) item2=:(i2,p2,(l2,t2,w2,h2),c2)
  380.     =    (mx`,my`,[(i1,p1,(l1,t2,w1,h1),c1),item2]);
  381.     where {
  382.         mx` = Max maxx (l1 + w1);    my` = Max maxy (t2 + h1);    l1 = l2+w2+ofs;
  383.     };
  384.  
  385. RightToRenter :: !Int !Int !Int !Int !ItPos ![CPos] -> (!Int,!Int,![CPos]);
  386. RightToRenter maxx maxy ofs id ipos [cpos=:(ic,rc):rest]
  387. |    id <> ic    = (mx1,my1,[cpos : rest`]);
  388.                 = (mx2,my2,[cpos, (i1,(l1,t2,w1,h1)) : rest]);
  389.     where {
  390.         (mx1,my1,rest`) = RightToRenter maxx maxy ofs id ipos rest;
  391.         mx2    = Max maxx (l1 + w1);    my2                = Max maxy (t2 + h1);
  392.         l1    = l2+w2+ofs;            (ld,td,w1,h1)    = r1;    (l2,t2,w2,h2) = rc;
  393.         (i1,ps,r1,c1) = ipos;
  394.     };
  395.  
  396. PositionBelow :: !Int !Int !Int !Int !ItPos !ItPos -> (!Int,!Int,!ItPos);
  397. PositionBelow maxx maxy ofs hmg item1=:(i1,p1,r1,c1) (i2,Center,r2,poss)
  398.     =    (mx`,my`,(i1,Center,(hmg,t1,w1,h1),c1));
  399.     where {
  400.         mx`    = Max maxx (hmg + w1);  my`                = Max maxy (t1 + h1);
  401.         t1    = t2+h2+ofs;            (ld,td,w1,h1)    = r1;    (l2,t2,w2,h2) = r2;
  402.     };
  403. PositionBelow maxx maxy ofs hmg item1=:(i1,p1,r1,c1) (i2,Right,r2,poss)
  404.     =    (mx`,my`,(i1,Right,(hmg,t1,w1,h1),c1));
  405.     where {
  406.         mx`    = Max maxx (hmg + w1);    my`                = Max maxy (t1 + h1);
  407.         t1    = t2+h2+ofs;            (ld,td,w1,h1)    = r1;    (l2,t2,w2,h2) = r2;
  408.     };
  409. PositionBelow maxx maxy ofs hmg (i1,p1,(ld,td,w1,h1),c1) item2=:(i2,p2,(l2,t2,w2,h2),c2)
  410.     =    (mx`,my`,(i1,p1,(l2,t1,w1,h1),c1));
  411.     where {
  412.         mx` = Max maxx (l2 + w1);    my` = Max maxy (t1 + h1);    t1 = t2+h2+ofs;
  413.     };
  414.  
  415. RemoveItPos    :: !Int ![ItPos] -> (!Bool,!ItPos,![ItPos]);
  416. RemoveItPos rid [ip=:(iid,Center,r,cits):rest]
  417. |    rid <> iid && not (ItPosInRenterList rid cits)    = (exists,pos,[ip:rest`]);
  418.                                                     = (True,ip,rest);
  419.     where {
  420.         (exists,pos,rest`) = RemoveItPos rid rest;
  421.     };
  422. RemoveItPos rid [ip=:(iid,Right,r,cits):rest]
  423. |    rid <> iid && not (ItPosInRenterList rid cits)    = (exists,pos,[ip:rest`]);
  424.                                                     = (True,ip,rest);
  425.     where {
  426.         (exists,pos,rest`) = RemoveItPos rid rest;
  427.     };
  428. RemoveItPos rid [ip=:(iid,p,r,c):rest]
  429. |    rid <> iid    = (exists,pos,[ip:rest`]);
  430.                 = (True,ip,rest);
  431.     where {
  432.         (exists,pos,rest`) = RemoveItPos rid rest;
  433.     };
  434. RemoveItPos _ [] = (False,DummyItPos,[]);
  435.  
  436. ItPosInRenterList :: !Int ![CPos] -> Bool;
  437. ItPosInRenterList iid [(cid,r):rest] | iid == cid    = True;
  438.                                                     = ItPosInRenterList iid rest;
  439. ItPosInRenterList _ [] = False;
  440.  
  441.  
  442. /*    After positioning the items the Center/Right items must be repositioned
  443.     according to the width of the dialog retrieved in the previous pass. */
  444.  
  445. RenterItems    :: !Int !Int ![ItPos] ![ItPos] -> [ItPos];
  446. RenterItems wid hmg [(id,Center,(l,t,w,h),cits):rest] poss
  447.     =    RenterItems wid hmg rest [(id,Center,(l + delta,t,w,h),cits`):poss];
  448.     where {
  449.         cits` = ShiftRenterItems delta cits;
  450.         delta = (wid - (RenterItemsMaxX (l + w) cits + hmg))/2;
  451.     };
  452. RenterItems wid hmg [(id,Right,(l,t,w,h),cits):rest] poss
  453.     =    RenterItems wid hmg rest [(id,Right,(l + delta,t,w,h),cits`):poss];
  454.     where {
  455.         cits` = ShiftRenterItems delta cits;
  456.         delta = wid - (RenterItemsMaxX (l + w) cits + hmg);
  457.     };
  458. RenterItems wid hmg [item:rest] poss
  459.     =    RenterItems wid hmg rest [item:poss];
  460. RenterItems _ _ [] poss = poss;
  461.  
  462. ShiftRenterItems :: !Int ![CPos] -> [CPos];
  463. ShiftRenterItems delta [(id,(l,t,w,h)):rest]
  464.     =    [(id,(l + delta,t,w,h)) : ShiftRenterItems delta rest];
  465. ShiftRenterItems _ [] = [];
  466.  
  467. RenterItemsMaxX    :: !Int ![CPos] -> Int;
  468. RenterItemsMaxX max [(id,(l,t,w,h)):rest] = RenterItemsMaxX (Max max (l + w)) rest;
  469. RenterItemsMaxX max [] = max;
  470.  
  471.  
  472. /*    After positioning/rentering the items the list of Rects must be transformed to
  473.     ItemBoxes and added to the original list of items. This routine also checks
  474.     whether the default id of RadioButtons or a DialogPopUps really exist. If not,
  475.     the first RadioItem in the list is chosen to be the initially marked item. */
  476.  
  477. AddItemBoxes :: ![ItPos] ![DialogItem s io] -> [DialogItem s io];
  478. AddItemBoxes poss [DialogButton id pos txt s f : items]
  479.     =    [DialogButton id ibox txt s f : AddItemBoxes poss` items];
  480.     where {
  481.         (ibox,poss`) = GetItemPosition id poss;
  482.     };
  483. AddItemBoxes poss [DialogIconButton id pos pd l s f : items]
  484.     =    [DialogIconButton id ibox pd l s f : AddItemBoxes poss` items]; 
  485.     where {
  486.         (ibox,poss`) = GetItemPosition id poss;
  487.     };
  488. AddItemBoxes poss [StaticText id pos txt : items]
  489.     =    [StaticText id ibox txt : AddItemBoxes poss` items]; 
  490.     where {
  491.         (ibox,poss`) = GetItemPosition id poss;
  492.     };
  493. AddItemBoxes poss [DynamicText id pos wid txt : items]
  494.     =    [DynamicText id ibox wid txt : AddItemBoxes poss` items]; 
  495.     where {
  496.         (ibox,poss`) = GetItemPosition id poss;
  497.     };
  498. AddItemBoxes poss [EditText id pos wid nrl t : items]
  499.     =    [EditText id ibox wid nrl t : AddItemBoxes poss` items]; 
  500.     where {
  501.         (ibox,poss`) = GetItemPosition id poss;
  502.     };
  503. AddItemBoxes poss [DialogPopUp id pos ab di buts : items]
  504.     =    [DialogPopUp id ibox ab di` buts : AddItemBoxes poss` items]; 
  505.     where {
  506.         (ibox,poss`)= GetItemPosition id poss;
  507.         di`            = CheckDefaultRadioItemId di buts;
  508.     };
  509. AddItemBoxes poss [RadioButtons id pos roc di buts : items]
  510.     =    [RadioButtons id ibox` roc di` buts : AddItemBoxes poss` items];
  511.     where {
  512.         ibox`       = RadioBoxItemBox (Length_new buts) roc ibox;
  513.         (ibox,poss`)= GetItemPosition id poss;
  514.         di`            = CheckDefaultRadioItemId di buts;
  515.     };
  516. AddItemBoxes poss [CheckBoxes id pos roc boxes : items]
  517.     =    [CheckBoxes id ibox` roc boxes : AddItemBoxes poss` items]; 
  518.     where {
  519.         ibox`       = RadioBoxItemBox (Length_new boxes) roc ibox;
  520.         (ibox,poss`)= GetItemPosition id poss;
  521.     };
  522. AddItemBoxes poss [Control id pos pd a s l f d : items]
  523.     =    [Control id ibox pd a s l f d : AddItemBoxes poss` items];
  524.     where {
  525.         (ibox,poss`)= GetItemPosition id poss;
  526.     };
  527. AddItemBoxes _ [] = [];
  528.  
  529. GetItemPosition    :: !Int ![ItPos] -> (!ItemPos,![ItPos]);
  530. GetItemPosition iid poss=:[pos=:(pid,ps=:Center,rect,cits):rest]
  531. |    iid == pid    = (ItemBox l t w h,poss);
  532. |    inclist        = (ibox,[(pid,ps,rect,cits`):rest]);
  533.                 = ( box,[pos:rest`]);
  534.     where {
  535.         (inclist,ibox,cits`)= FindItemBoxInRenterList iid cits;
  536.         (box,rest`)            = GetItemPosition iid rest;
  537.         (l,t,w,h)            = rect;
  538.     };
  539. GetItemPosition iid poss=:[pos=:(pid,ps=:Right,rect,cits):rest]
  540. |    iid == pid    = (ItemBox l t w h,poss);
  541. |    inclist        = (ibox,[(pid,ps,rect,cits`):rest]);
  542.                 = (box,[pos:rest`]);
  543.     where {
  544.         (inclist,ibox,cits`)= FindItemBoxInRenterList iid cits;
  545.         (box,rest`)            = GetItemPosition iid rest;
  546.         (l,t,w,h)            = rect;
  547.     };
  548. GetItemPosition iid [pos=:(pid,ps,rect,cits):rest]
  549. |    iid == pid    = (ItemBox l t w h, rest);
  550.                 = (box,[pos:rest`]);
  551.     where {
  552.         (box,rest`)    = GetItemPosition iid rest;
  553.         (l,t,w,h)    = rect;
  554.     };
  555. GetItemPosition _ []
  556.     =    DialogLayoutError "GetItemPosition" "Unknown item id";
  557.  
  558. FindItemBoxInRenterList    :: !Int ![CPos] -> (!Bool,!ItemPos,![CPos]);
  559. FindItemBoxInRenterList iid [cpos=:(cid,rect):rest]
  560. |    iid == cid    = (True,ItemBox l t w h,rest);
  561.                 = (found,box,[cpos:rest`]);
  562.     where {
  563.         (found,box,rest`)    = FindItemBoxInRenterList iid rest;
  564.         (l,t,w,h)            = rect;
  565.     };
  566. FindItemBoxInRenterList _ rest = (False,Left,rest);
  567.  
  568. RadioBoxItemBox    :: !Int !RowsOrColumns !ItemPos -> ItemPos;
  569. RadioBoxItemBox nrb (Rows nr) (ItemBox l t w h) =  ItemBox l t (Div w (UpDiv nrb nr)) (Div h nr);
  570. RadioBoxItemBox nrb (Columns nc) (ItemBox l t w h) =  ItemBox l t (Div w nc) (Div h (UpDiv nrb nc));
  571.  
  572. CheckDefaultRadioItemId    :: !DialogItemId ![RadioItemDef s io] -> DialogItemId;
  573. CheckDefaultRadioItemId did items=:[RadioItem fid tt ab df : rest]
  574.     =  CheckDefRadioItemId fid did items;
  575. CheckDefaultRadioItemId did []
  576.     =  DialogLayoutError "in dialog definition" "empty list of RadioItems";
  577.  
  578. CheckDefRadioItemId    :: !DialogItemId !DialogItemId ![RadioItemDef s io] -> DialogItemId;
  579. CheckDefRadioItemId fid did [RadioItem id tt ab df : rest]
  580. |    id == did    = did;
  581.                 = CheckDefRadioItemId fid did rest;
  582. CheckDefRadioItemId fid _ _ = fid;
  583.  
  584.  
  585. //    DialogFont returns the standard dialog font: Chicago 12.
  586.  
  587. DialogFont :: Font;
  588. DialogFont = font;
  589.     where {
  590.         (_,font) = SelectFont "Chicago" [] 12;
  591.     };
  592.  
  593. //    Calculations from Measures (inches, millimeters or pixels) to screen pixels.
  594.  
  595. HorMeasureToPixels    :: !Measure  -> Int;
  596. HorMeasureToPixels (Pixel    p) = ABS p;
  597. HorMeasureToPixels (Inch    i) = InchesToHPixels (ABSR i);
  598. HorMeasureToPixels (MM        m) = InchesToHPixels (ABSR m / MMPerInch);
  599.  
  600. VerMeasureToPixels    :: !Measure  -> Int;
  601. VerMeasureToPixels (Pixel    p) = ABS p;
  602. VerMeasureToPixels (Inch    i) = InchesToVPixels (ABSR i);
  603. VerMeasureToPixels (MM        m) = InchesToVPixels (ABSR m / MMPerInch);
  604.  
  605. InchesToHPixels    :: !Real -> Int;
  606. InchesToHPixels i = toInt (i * toReal hRes);
  607.     where {
  608.         (hRes,_) = LoadWord ScrnHResAddress NewToolbox;
  609.     };
  610.  
  611. InchesToVPixels    :: !Real -> Int;
  612. InchesToVPixels i = toInt (i * toReal vRes);
  613.     where {
  614.         (vRes,_) = LoadWord ScrnVResAddress NewToolbox;
  615.     };
  616.